package org.kth.dks.util;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.apache.log4j.*;

public class DKSPrint {
  private static int logLevel = 1; // 0 means disabled
  private static Map a_enabledEntries = new HashMap();

  private static LinkedList debugInfo = new LinkedList();
  
  static {
//      enableType(DKSPrintTypes.SENDER);
	    enableType(DKSPrintTypes.ERROR);
	    enableType(DKSPrintTypes.DKSNODE);
	    enableType(DKSPrintTypes.TEST);
	    enableType(DKSPrintTypes.TEST_BED);
//      enableType(DKSPrintTypes.MSGS);
  }

  private static void addDebugInfo(String data) {
    //debugInfo.addLast( data );
  }

  /**
   * Sets the logging level, 0 for no logging, 1 for printing of debug info
   * that has been explicitly enabled, 2 for every thing, including XML dumps
   * @param level int
   */
  public static void logLevel(int level) {
    logLevel = level;
  }

  /**
   * Enables logging for a group of log messages defined by the string argument.
   * @param type the identfifier for the group of log info
   */
  public static void enableType(DKSPrintTypes type) {
    // For now I just put the string as value in the HT,
    // later we can change this and put the target for the
    // log infor, i.e. a file or stdout.
    a_enabledEntries.put(type, type);

  }

  /**
   * Disables logging for a group of log messages defined by the string argument.
   * @param type the identfifier for the group of log info
   */
  public static void disableType(DKSPrintTypes type) {
    a_enabledEntries.remove(type);
  }

  /**
   * Prints the data string, if the type of loginfo is enabled for
   * printing. The type is not automatically displayed.
   * @param type type of loginfo
   * @param data String to be printed
   */

  public static void print(DKSPrintTypes type, String data) {
    if (displayString(type)) {
      System.out.print(data);
      addDebugInfo(data);
    }
  }

  /**
   * like <code>Print</code> with additional line feed.
   * Moreover, the type of loginfo is attached the output.
   * @param type type of loginfo
   * @param data String to be printed
   */

  public static void println(DKSPrintTypes type, String data) {
    if (displayString(type)) {
      System.out.println(type + ":" + data);
      addDebugInfo(type + ":" + data + "\n");
    }
  }

  /**
   * like <code>Print</code> with additional line feed.
   * @param data String to be printed
   */

  public static void println_noType(DKSPrintTypes type, String data) {
    if (displayString(type)) {
      System.out.println(data);
      addDebugInfo(data + "\n");
    }
  }

  /**
   * like <code>Print</code> with additional line feed
   * @param data char to be printed
   */
  public static void print(DKSPrintTypes type, char data) {
    if (displayString(type)) {
      System.out.print(data);
      addDebugInfo("" + data);
    }
  }

  /**
   * like <code>Print</code> with additional line feed
   * @param byte char to be printed
   */
  public static void print(DKSPrintTypes type, byte data) {
    if (displayString(type) || logLevel == 1) {
      System.out.print(data);
      addDebugInfo("" + data);
    }
  }

  /**
   * Prints a marshalled XML message
   * @param arr byte[] is the byte array to print
   * @param sending boolean indicates whether the messages is to be sent or received
   */
  public static void printXML(byte[] arr, boolean sending) {
    if (logLevel > 2) {
      System.out.print(" ###### XML MSG BEG ###### ");
      addDebugInfo(" ###### XML MSG BEG ###### ");
      System.out.println( (sending ? "SEND" : "RECV"));
      addDebugInfo( (sending ? "SEND" : "RECV") + "\n");
      for (int x = 0; x < arr.length; x++) {
        System.out.print( (char) arr[x]);
        addDebugInfo("" + (char) arr[x]);
      }
      System.out.println(" ###### XML MSG END ########## ");
      addDebugInfo(" ###### XML MSG END ########## " + "\n");
    }
  }

  /**
   * Cuts the string if it is longer than MAXLEN=75 characters long
   * @param str is the string to be pretty printed
   * @return String
   */
  public static String prettyPrint(String str) {
    final int MAXLEN = 75;
    return (str.length() < MAXLEN ?
            str :
            str.substring(0, MAXLEN) + "..." + str.substring(str.length() - 3)
        );
  }

  private static boolean displayString(DKSPrintTypes type) {
//    if (1!=2) return true;
    switch (logLevel) {
      case 0:
        return false;
      case 1:
        return a_enabledEntries.get(type) != null;
      case 2:
      default:
        return true;
    }
  }

  /**
   * Define a Serializable object to return the debug information.
   * It has a toString() method to get the debug info.
   */
  static class DebugInfo implements java.io.Serializable {
    private String data = null;

    public DebugInfo(LinkedList debugInfo) {
      data = "";

      for (int i = 0; i < debugInfo.size(); i++) {
        data = data + debugInfo.get(i);
      }
    }

    public String toString() {
      return data;
    }
  }

  /**
   * Get debug information.
   * @return Serializable The object containing debug info.
   */
  public static java.io.Serializable getDebugInfo() {
    DebugInfo newDebugInfo = new DebugInfo(debugInfo);

    debugInfo.clear();

    return newDebugInfo;
  }
}
